package chain_apply

import (
	"chain_bridge_service/internal/services/chain_apply"
	"chain_bridge_service/internal/services/chain_to_chain"
	"chain_bridge_service/pkg/errors"
	"net/http"
	"strconv"

	"chain_bridge_service/internal/code"
	"chain_bridge_service/internal/pkg/core"
	"chain_bridge_service/internal/pkg/validation"
)

type createRequest struct {
	ChainConfigId0 string `bson:"chainConfigId0" json:"chainConfigId0"`
	ChainConfigId1 string `bson:"chainConfigId1" json:"chainConfigId1"`
	TokenId0       string `bson:"tokenId0" json:"tokenId0"`
	TokenId1       string `bson:"tokenId1" json:"tokenId1"`
	TxHash         string `bson:"txHash" json:"txHash"`
	From           string `bson:"from" json:"from"`
	To             string `bson:"to" json:"to"`
	UserId         string `bson:"userId" json:"userId"`
	Amount0        string `bson:"amount0" json:"amount0"`
	Amount1        string `bson:"amount1" json:"amount1"`
}

type createResponse struct {
	Code int         `json:"code"`
	Data interface{} `json:"data"`
	Msg  string      `json:"msg"`
}

func (h *handler) Create() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(createRequest)
		res := new(createResponse)
		if err := ctx.ShouldBindJSON(req); err != nil {
			ctx.AbortWithError(core.Error(
				http.StatusOK,
				code.ParamBindError,
				validation.Error(err)),
			)
			return
		}

		if req.ChainConfigId0 == req.ChainConfigId1 || req.TokenId0 == req.TokenId1 {
			ctx.AbortWithError(core.Error(
				http.StatusOK,
				code.ExchangeError,
				validation.Error(errors.New("链或者代币地址相同"))),
			)
			return
		}

		data := new(chain_to_chain.CreateChainData)
		data.Token1 = req.TokenId1
		data.Token0 = req.TokenId0
		data.ChainConfigId0 = req.ChainConfigId0
		data.ChainConfigId1 = req.ChainConfigId1
		data.UserId = req.UserId

		chainInfo, err := h.chainService.GetRate(ctx, data)
		if err != nil {
			ctx.AbortWithError(core.Error(
				http.StatusOK,
				code.GetProductListError,
				code.Text(code.GetProductListError)).WithError(err),
			)
			return
		}

		amountInt, _ := strconv.Atoi(req.Amount0)
		if chainInfo.MaxNumber != 0 && chainInfo.MaxNumber < uint64(amountInt) {
			ctx.AbortWithError(core.Error(
				http.StatusOK,
				code.GetUserCountError,
				code.Text(code.GetProductListError)).WithError(err),
			)
			return
		}

		createData := new(chain_apply.RequestData)
		createData.UserId = req.UserId
		createData.To = req.To
		createData.From = req.From
		createData.TxHash = req.TxHash
		createData.TokenId1 = req.TokenId1
		createData.TokenId0 = req.TokenId0
		createData.ChainConfigId1 = req.ChainConfigId1
		createData.ChainConfigId0 = req.ChainConfigId0
		createData.Amount0 = req.Amount0
		createData.Amount1 = req.Amount1

		err = h.chainApplyService.Create(ctx, createData)
		if err != nil {
			ctx.AbortWithError(core.Error(
				http.StatusOK,
				code.ExchangeError,
				code.Text(code.ExchangeError)).WithError(err),
			)
			return
		}

		res.Code = code.StatusOK
		res.Data = nil
		res.Msg = code.Text(code.StatusOK)
		ctx.Payload(res)
	}
}
